#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
打包脚本
用于将Flask Web应用程序打包成可执行的exe文件
"""

import os
import sys
import subprocess
import shutil
import io
import time

print("[DEBUG] Starting build_exe.py script")
print("[DEBUG] Current Python version: %s.%s.%s" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]))
print("[DEBUG] Current working directory: %s" % os.getcwd())

# 解决Windows系统上的编码问题
if sys.version_info[0] == 2:
    print("[DEBUG] Python 2 environment detected, setting up UTF-8 encoding")
    # 设置默认编码为utf-8
    reload(sys)
    sys.setdefaultencoding('utf-8')
    print("[DEBUG] Default encoding set to: %s" % sys.getdefaultencoding())
    
    # 在Python 2.7中不重定向标准输出，避免显示问题
    print("[DEBUG] UTF-8 encoding set up successfully")
else:
    print("[DEBUG] Running in Python 3+ environment")

# 检查Python版本
if sys.version_info[0] != 2 or sys.version_info[1] != 7:
    print("[WARNING] This script is designed for Python 2.7 environment.")
    print("[WARNING] Current version: %s.%s.%s" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]))
    sys.exit(1)

# 项目根目录
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
print("[DEBUG] Project root directory: %s" % PROJECT_ROOT)
# 打包输出目录
DIST_DIR = os.path.join(PROJECT_ROOT, 'dist')
print("[DEBUG] Distribution directory: %s" % DIST_DIR)
# 构建目录
BUILD_DIR = os.path.join(PROJECT_ROOT, 'build')
print("[DEBUG] Build directory: %s" % BUILD_DIR)
# 应用程序入口文件
APP_ENTRY = 'app.py'
print("[DEBUG] Application entry: %s" % APP_ENTRY)
# 应用程序名称（带时间戳后缀用于版本区分）
BASE_APP_NAME = 'WebTools'
BUILD_TIMESTAMP = time.strftime('%Y%m%d%H%M')
APP_NAME = '%s_%s' % (BASE_APP_NAME, BUILD_TIMESTAMP)
print("[DEBUG] Application base name: %s" % BASE_APP_NAME)
print("[DEBUG] Build timestamp: %s" % BUILD_TIMESTAMP)
print("[DEBUG] Final application name: %s" % APP_NAME)


def check_pyinstaller():
    """检查PyInstaller是否已安装"""
    print("[DEBUG] Checking if PyInstaller is installed...")
    try:
        # 使用系统命令检查pyinstaller，避免编码问题
        print("[DEBUG] Running command: pyinstaller --version")
        result = subprocess.call(['pyinstaller', '--version'], 
                               stdout=open(os.devnull, 'w'), 
                               stderr=open(os.devnull, 'w'))
        print("[DEBUG] PyInstaller check result: %d (0=installed)" % result)
        return result == 0
    except OSError as e:
        print("[ERROR] OSError when checking PyInstaller: %s" % str(e))
        return False
    except subprocess.CalledProcessError as e:
        print("[ERROR] CalledProcessError when checking PyInstaller: %s" % str(e))
        return False
    except Exception as e:
        print("[ERROR] Unexpected error when checking PyInstaller: %s" % str(e))
        return False


def install_requirements():
    """安装项目依赖"""
    print("[DEBUG] Starting dependency installation...")
    requirements_file = os.path.join(PROJECT_ROOT, 'requirements.txt')
    print("[DEBUG] Requirements file: %s" % requirements_file)
    
    # 检查requirements.txt是否存在
    if not os.path.exists(requirements_file):
        print("[ERROR] Requirements file not found: %s" % requirements_file)
        sys.exit(1)
    
    try:
        # 显示requirements.txt内容
        print("[DEBUG] Reading requirements.txt content...")
        with open(requirements_file, 'r') as f:
            requirements_content = f.read()
        print("[DEBUG] Requirements content:\n%s" % requirements_content)

        # 先尝试将 pip/setuptools/wheel 升级到 Python 2.7 可用的最后版本
        bootstrap_cmds = [
            [sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip==20.3.4'],
            [sys.executable, '-m', 'pip', 'install', '--upgrade', 'setuptools==44.1.1'],
            [sys.executable, '-m', 'pip', 'install', '--upgrade', 'wheel==0.34.2'],
        ]
        for cmd in bootstrap_cmds:
            print("[DEBUG] Bootstrapping: %s" % ' '.join(cmd))
            try:
                subprocess.check_call(cmd)
            except Exception as e:
                print("[WARNING] Bootstrap step failed (continuing): %s" % str(e))

        # 常规安装，输出不再重定向，便于看到真实错误
        cmd = [sys.executable, '-m', 'pip', 'install', '-r', requirements_file]
        print("[DEBUG] Running pip install command: %s" % ' '.join(cmd))
        start_time = time.time()
        subprocess.check_call(cmd)
        end_time = time.time()
        print("[DEBUG] Dependencies installed successfully in %.2f seconds!" % (end_time - start_time))
    except subprocess.CalledProcessError as e:
        print("[ERROR] Dependency installation failed: %s" % str(e))
        # 自动使用国内镜像重试一次，并添加 trusted-host 以缓解 TLS/SNI 问题
        try:
            mirror_cmd = [
                sys.executable, '-m', 'pip', 'install', '-r', requirements_file,
                '-i', 'https://pypi.tuna.tsinghua.edu.cn/simple',
                '--trusted-host', 'pypi.tuna.tsinghua.edu.cn',
                '--trusted-host', 'pypi.org',
                '--trusted-host', 'files.pythonhosted.org'
            ]
            print("[DEBUG] Retrying with mirror: %s" % ' '.join(mirror_cmd))
            subprocess.check_call(mirror_cmd)
            print("[DEBUG] Dependencies installed successfully via mirror!")
        except Exception as e2:
            print("[ERROR] Mirror install also failed: %s" % str(e2))
            print("[HINT] Possible causes on Python 2.7: old pip/OpenSSL TLS 1.2, network/proxy, or wheel not available.")
            print("[HINT] Ensure pip==20.3.4, setuptools==44.1.1, wheel==0.34.2, and retry.")
            sys.exit(1)
    except Exception as e:
        print("[ERROR] Unexpected error during dependency installation: %s" % str(e))
        sys.exit(1)


def build_exe():
    """使用PyInstaller打包应用程序"""
    print("[DEBUG] Starting application build process...")
    
    # 检查入口文件是否存在
    app_entry_path = os.path.join(PROJECT_ROOT, APP_ENTRY)
    if not os.path.exists(app_entry_path):
        print("[ERROR] Application entry file not found: %s" % app_entry_path)
        sys.exit(1)
    print("[DEBUG] Application entry file exists: %s" % app_entry_path)
    
    # 检查templates目录是否存在
    templates_dir = os.path.join(PROJECT_ROOT, 'templates')
    if not os.path.exists(templates_dir):
        print("[ERROR] Templates directory not found: %s" % templates_dir)
        sys.exit(1)
    print("[DEBUG] Templates directory exists: %s" % templates_dir)
    
    # 检查static目录是否存在
    static_dir = os.path.join(PROJECT_ROOT, 'static')
    if not os.path.exists(static_dir):
        print("[ERROR] Static directory not found: %s" % static_dir)
        sys.exit(1)
    print("[DEBUG] Static directory exists: %s" % static_dir)
    
    # 清理旧的构建文件
    print("[DEBUG] Cleaning up old build files...")
    if os.path.exists(DIST_DIR):
        print("[DEBUG] Removing dist directory: %s" % DIST_DIR)
        shutil.rmtree(DIST_DIR)
    else:
        print("[DEBUG] dist directory not found, skipping removal")
        
    if os.path.exists(BUILD_DIR):
        print("[DEBUG] Removing build directory: %s" % BUILD_DIR)
        shutil.rmtree(BUILD_DIR)
    else:
        print("[DEBUG] build directory not found, skipping removal")
        
    # 清理旧的 spec 文件（匹配同一基名）
    removed_spec = False
    for fname in os.listdir(PROJECT_ROOT):
        if fname.startswith(BASE_APP_NAME) and fname.endswith('.spec'):
            try:
                os.remove(os.path.join(PROJECT_ROOT, fname))
                print("[DEBUG] Removed old spec file: %s" % fname)
                removed_spec = True
            except Exception as e:
                print("[WARNING] Failed to remove old spec file %s: %s" % (fname, str(e)))
    if not removed_spec:
        print("[DEBUG] No old spec files found to remove")
    
    print("[DEBUG] Building application...")
    try:
        # 构建PyInstaller命令
        cmd = [
            'pyinstaller',
            '--name=%s' % APP_NAME,
            '--onefile',  # 打包成单个可执行文件
            '--console',  # 显示控制台以查看日志
            '--hidden-import=email',
            '--hidden-import=email.mime',
            '--hidden-import=email.parser',
            '--hidden-import=email.generator',
            '--add-data=templates;templates',  # 添加templates目录
            '--add-data=static;static',  # 添加static目录
            APP_ENTRY
        ]
        
        print("[DEBUG] PyInstaller command: %s" % ' '.join(cmd))
        print("[DEBUG] Command working directory: %s" % PROJECT_ROOT)
        print("[DEBUG] Starting PyInstaller process... (this may take several minutes)")
        
        start_time = time.time()
        # 不重定向输出，以便查看详细日志
        subprocess.check_call(cmd, cwd=PROJECT_ROOT)
        end_time = time.time()
        
        print("\n[DEBUG] Build successful! Total time: %.2f seconds" % (end_time - start_time))
        print("[DEBUG] Executable location: %s" % os.path.join(DIST_DIR, APP_NAME + '.exe'))
        print("\n[INFO] Usage instructions:")
        print("[INFO] 1. Double click %s.exe to run the application" % APP_NAME)
        print("[INFO] 2. Open browser and visit http://localhost:5000")
        print("[INFO] 3. Use the tools provided")
        print("\n[INFO] Note: If firewall prompts, allow the program to access the network.")
        
        # 验证构建结果
        exe_path = os.path.join(DIST_DIR, APP_NAME + '.exe')
        if os.path.exists(exe_path):
            print("[DEBUG] Successfully verified executable exists: %s" % exe_path)
            print("[DEBUG] Executable size: %.2f MB" % (os.path.getsize(exe_path) / (1024 * 1024)))
        else:
            print("[WARNING] Executable not found at expected location: %s" % exe_path)
        
    except subprocess.CalledProcessError as e:
        print("[ERROR] Build failed with return code %d: %s" % (e.returncode, str(e)))
        sys.exit(1)
    except OSError as e:
        print("[ERROR] OS error occurred during build: %s" % str(e))
        sys.exit(1)
    except Exception as e:
        print("[ERROR] Unexpected error during build: %s" % str(e))
        sys.exit(1)


def main():
    """主函数"""
    print("[DEBUG] === Web Tools Build Script ===")
    print("[DEBUG] Starting main function execution")
    
    # 检查并安装PyInstaller
    print("[DEBUG] Calling check_pyinstaller() function")
    if not check_pyinstaller():
        print("[DEBUG] PyInstaller not found, installing from requirements.txt...")
        install_requirements()
    else:
        print("[DEBUG] PyInstaller is already installed")
    
    # 开始打包
    print("[DEBUG] Calling build_exe() function")
    build_exe()
    print("[DEBUG] Main function execution completed")


if __name__ == '__main__':
    print("[DEBUG] Script is being run directly")
    start_time = time.time()
    main()
    end_time = time.time()
    print("[DEBUG] Total script execution time: %.2f seconds" % (end_time - start_time))